﻿using log4net.Config;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

//[assembly: log4net.Config.XmlConfigurator(Watch = true)]
namespace SuperJoe.Framework.Logging
{
    public class Log4netLogger : ILogger
    {
        private const string LOGGER_NAME_DEBUG = "debug";
        private const string LOGGER_NAME_ERROR = "error";
        private const string LOGGER_NAME_INFO = "info";
        private const string LOGGER_NAME_WARN = "warn";
        private const string LOGGER_NAME_FATAL = "fatal";

        private struct LogModel
        {
            [JsonProperty(propertyName: "time", Order = 1)]
            public string Time;

            [JsonProperty(propertyName: "app", Order = 2)]
            public string App;

            [JsonProperty(propertyName: "host", Order = 2)]
            public string Host;

            [JsonProperty(propertyName: "ip", Order = 3)]
            public string IP;

            [JsonProperty(propertyName: "tid", Order = 4)]
            public string ThreadId;

            [JsonProperty(propertyName: "level", Order = 5)]
            public string LogLevel;

            [JsonProperty(propertyName: "class", Order = 6)]
            public string ClassName;

            [JsonProperty(propertyName: "method", Order = 7)]
            public string MethodName;

            [JsonProperty(propertyName: "msg", Order = 8)]
            public object Message;

            [JsonProperty(propertyName: "ex", Order = 9, NullValueHandling = NullValueHandling.Ignore)]
            public string Exception;

            [JsonProperty(propertyName: "data", Order = 10)]
            public object Data;

        }

        static Log4netLogger()
        {
            XmlConfigurator.ConfigureAndWatch(new System.IO.FileInfo(AppDomain.CurrentDomain.BaseDirectory + "\\log4net.config"));
        }

        public void Error(string message = null, Exception ex = null, Object data = null)
        {
            log4net.ILog log = log4net.LogManager.GetLogger(LOGGER_NAME_ERROR);
            log.Error(FormatMessage("ERROR", message, ex, data));
        }

        public void Fatal(string message = null, Exception ex = null, Object data = null)
        {
            log4net.ILog log = log4net.LogManager.GetLogger(LOGGER_NAME_FATAL);
            log.Fatal(FormatMessage("FATAL", message, ex, data));
        }

        public void Debug(string message, Object data = null)
        {
            log4net.ILog log = log4net.LogManager.GetLogger(LOGGER_NAME_DEBUG);
            log.Debug(FormatMessage(message, "DEBUG", data));
        }

        public void Info(string message, Object data = null)
        {
            log4net.ILog log = log4net.LogManager.GetLogger(LOGGER_NAME_INFO);
            log.Info(FormatMessage(message, "INFO", data));
        }

        public void Warn(string message, Object data = null)
        {
            log4net.ILog log = log4net.LogManager.GetLogger(LOGGER_NAME_WARN);
            log.Warn(FormatMessage(message, "WARN", data));
        }

        internal static string FormatMessage(string message, string logLevel, object data = null)
        {
            LogModel m = CreateLogModel(logLevel, message, data: data);

            return JsonConvert.SerializeObject(m);
        }

        internal static string FormatMessage(string logLevel, string message = null, Exception ex = null, object data = null)
        {
            var m = CreateLogModel(logLevel, message, ex, data);

            return JsonConvert.SerializeObject(m);
        }

        private static LogModel CreateLogModel(string logLevel, string message, Exception ex = null, object data = null)
        {
            var m = new LogModel();

            m.Message = message;
            m.LogLevel = logLevel;
            m.Time = DateTime.Now.ToString();
            m.ThreadId = System.Threading.Thread.CurrentThread.ManagedThreadId.ToString();
            m.Host = ConfigurationManager.AppSettings["Log.Host"];
            m.IP = ConfigurationManager.AppSettings["Log.IP"];
            m.App = ConfigurationManager.AppSettings["Log.APP"];
            m.Exception = ex == null ? null : ex.ToString();
            m.Data = data;

            return m;
        }


    }
}
